﻿using DNFImagePacks2Manager.Helpers;
using System.Collections.Generic;
using System.IO;
using Windows.Graphics.Imaging;

namespace DNFImagePacks2Manager.NPK
{
    public class IMGV5File : IMGFile, IConvertIMGV2
    {
        private static readonly List<int> bitmapType = [0x10, 0x0F, 0x0E];

        public int DDSCount { get; set; }
        public int ImgSize { get; set; }
        public ColorPanel ColorPanel { get; set; }
        public List<ImageDDSIndex> DDSIndexs { get; set; } = [];

        public IMGV5File(BinaryReader reader, IMGHeader imgHeader) : base(imgHeader){
            byte[] ddsCountBytes = reader.ReadBytes(4);
            byte[] imgSizeBytes = reader.ReadBytes(4);

            DDSCount = ByteHelper.Bytes2Int(ddsCountBytes);
            ImgSize = ByteHelper.Bytes2Int(imgSizeBytes);

            ColorPanel = new ColorPanel(reader);

            for (int i = 0; i < DDSCount; i++)
            {
                ImageDDSIndex ddsIndex = new(reader);
                DDSIndexs.Add(ddsIndex);
            }
            for (int i = 0; i < imgHeader.Count; i++)
            {
                Images.Add(ImageFile.ReadImageFile(reader));
            }
            foreach (var ddsIndex in DDSIndexs)
            {
                int size = ddsIndex.ImageSize;
                if (size > 0)
                {
                    ddsIndex.DataBytes = reader.ReadBytes(size);
                }
            }
            foreach (var image in Images)
            {
                int size = image.GetSize();
                if (size > 0)
                {
                    if (image is ImageBitmapFile bitmapFile)
                    {
                        bitmapFile.DataBytes = reader.ReadBytes(size);
                    }
                }
            }
        }

        public IMGV2File Convert2IMGV2File()
        {
            List<ImageFile> imageList = [];
            foreach (var image in Images)
            {
                ImageFile? newImage = image switch
                {
                    ImagePointerFile pointerImage => pointerImage,

                    ImageBitmapFile bitmapImage => IConvertIMGV2.ConvertBitmapFromColorPanel(bitmapImage),

                    ImageDDSFile ddsImage => ConvertBitmapFromDDS(ddsImage),

                    _ => null
                };

                if (newImage != null)
                {
                    imageList.Add(newImage);
                }
            }
            return new IMGV2File(Header, imageList);
        }

        public ImageBitmapFile? ConvertBitmapFromDDS(ImageDDSFile ddsImage)
        {
            byte[]? data = GetDDSFile(ddsImage.DDSIndex)?.GetMipmap()?.GetDataBytes(ddsImage, out _, out _);
            if (data != null)
            {
                return new ImageBitmapFile(
                    data,
                    ddsImage.ImageWidth, ddsImage.ImageHeight,
                    ddsImage.FrameWidth, ddsImage.FrameHeight,
                    ddsImage.PositionX, ddsImage.PositionY);
            }
            return null;
        }

        public override bool SetImage(int index, ImageFile image)
        {
            if (base.SetImage(index, image))
            {
                return true;
            }
            else
            {
                if (index < Images.Count)
                {
                    if (image is ImageBitmapFile bitmapImage)
                    {
                        if (bitmapType.Contains(bitmapImage.Type.TypeCode))
                        {

                            Images[index] = bitmapImage;
                            return true;
                        }
                    }
                    if (image is ImageDDSFile ddsImage)
                    {
                        return false;
                    }
                    return false;
                }
                else
                {
                    return false;
                }
            }
        }

        public DDSData? GetDDSFile(int index)
        {
            return index >= 0 && index < DDSIndexs.Count ? DDSIndexs[index].GetDDSFile() : null;
        }

        public override SoftwareBitmap? GetPreviewImage(int index, bool ignorePointer = true)
        {
            SoftwareBitmap? bitmap = base.GetPreviewImage(index, ignorePointer);
            if (bitmap == null)
            {
                if (index < Images.Count)
                {
                    ImageFile image = Images[index];
                    if (image is ImagePointerFile pointerImage && !ignorePointer)
                    {
                        return GetPreviewImage(pointerImage.Pointer, ignorePointer);
                    }
                    if (image is ImageBitmapFile bitmapImage)
                    {
                        return bitmapImage.GetPreviewImage();
                    }
                    if (image is ImageDDSFile ddsImage)
                    {
                        return GetDDSFile(ddsImage.DDSIndex)?.GetMipmap()?.GetPreviewImage(ddsImage);
                    }
                }
            }
            return bitmap;
        }

        public override byte[] GetBytes()
        {

            List<byte> bytes = [];
            List<byte> secondBytes = [];
            List<byte> indexBytes = [];
            List<byte> ddsBytes = [];
            List<byte> dataBytes = [];
            foreach (var image in Images)
            {
                indexBytes.AddRange(image.GetIndexBytes());
                if (image.GetSize() > 0)
                {
                    dataBytes.AddRange(image.DataBytes);
                }
            }
            bytes.AddRange(GetHeaderBytes(indexBytes.Count));
            bytes.AddRange(ByteHelper.Int2Bytes(DDSCount));
            secondBytes.AddRange(ColorPanel.GetBytes());
            foreach (var ddsIndex in DDSIndexs)
            {
                secondBytes.AddRange(ddsIndex.GetBytes());
                ddsBytes.AddRange(ddsIndex.DataBytes);
            }
            secondBytes.AddRange(indexBytes);
            secondBytes.AddRange(ddsBytes);
            secondBytes.AddRange(dataBytes);
            ImgSize = bytes.Count + secondBytes.Count + 4;
            bytes.AddRange(ByteHelper.Int2Bytes(ImgSize));
            bytes.AddRange(secondBytes);
            return [.. bytes];
        }


    }
}
